﻿#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:6031)

//描述
//输入10个整数，要求按输入时的逆序把这10个数打印出来。逆序输出，就是按照输入相反的顺序打印这10个数。
//输入描述：
//一行，输入10个整数（范围 - 231~231 - 1），用空格分隔。
//输出描述：
//一行，逆序输出输入的10个整数，用空格分隔。

//#include<stdio.h>
//int main()
//{
//	int i = 0;
//	int arr[10] = { 0 };
//	for (i = 0; i < 10; i++)
//	{
//		scanf("%d", &arr[i]);
//	}
//	for (i = 9; i >= 0; i--)
//	{
//		printf("%d ", arr[i]);
//	}
//	return 0;
//
//}

//
//输入数字N，然后输入N个数，计算这N个数的和。
//输入描述：
//第一行输入一个整数N(0≤N≤50)，第二行输入用空格分隔的N个整数。
//输出描述：
//输出为一行，为第二行输入的“N个整数之和”的计算结果。

//#include<stdio.h>
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	int i = 0;
//	int sum = 0;
//	int num = 0;
//	for (i = 0; i < n; i++)
//	{
//		scanf("%d", &num);	//scanf遇到空格就回停止
//		sum += num;
//	}
//	printf("%d\n", sum);
//	return 0;
//}


//描述
//输入n个成绩，换行输出n个成绩中最高分数和最低分数的差。
//输入描述：
//两行，第一行为n，表示n个成绩，不会大于10000。
//
//第二行为n个成绩（整数表示，范围0~100），以空格隔开。
//输出描述：
//一行，输出n个成绩中最高分数和最低分数的差。

//#include<stdio.h>
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	int max = 0;
//	int min = 0;
//	int num = 0;
//	for (int i = 0; i < n; i++)
//	{
//		scanf("%d", &num);
//		if (i == 0)
//		{
//			max = num;
//			min = num;
//		}
//		if (num > max)
//		{
//			max = num;
//		}
//		else if (num < min)
//		{
//			min = num;
//		}
//	}
//	printf("%d\n", max - min);
//	return 0;
//}

//期中考试开始了，大家都想取得好成绩，争夺前五名。从键盘输入 n 个学生成绩，输出每组排在前五高的成绩。
//
//数据范围： 5 \le n \le 50 \5≤n≤50  ，成绩采取百分制并不会出现负数
//输入描述：
//两行，第一行输入一个整数，表示n个学生（ >= 5），第二行输入n个学生成绩（整数表示，范围0~100），用空格分隔。
//输出描述：
//一行，输出成绩最高的前五个，用空格分隔。
//
//#include<stdio.h>
//#include<stdlib.h>
//int cmp(const void* e1, const void* e2)
//{
//	return *(int*)e2 - *(int*)e1;
//}
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	if (n >= 5)
//	{
//		int* arr = (int*)malloc(sizeof(int) * n);
//		int i = 0;
//		for (i = 0; i < n; i++)
//		{
//			scanf("%d", &arr[i]);
//		}
//		qsort(arr, n, sizeof(int), cmp);
//		for (i = 0; i < 5; i++)
//		{
//			printf("%d ", arr[i]);
//		}
//	}
//	return 0;
//}


//
//输入一个整数序列，判断是否是有序序列，有序，指序列中的整数从小到大排序或者从大到小排序(相同元素也视为有序)。
//
//数据范围： 3 \le n \le 50 \3≤n≤50  序列中的值都满足 1 \le val \le 100 \1≤val≤100
//输入描述：
//第一行输入一个整数N(3≤N≤50)。
//第二行输入N个整数，用空格分隔N个整数。
//输出描述：
//输出为一行，如果序列有序输出sorted，否则输出unsorted。
//示例1

//#include<stdio.h>
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	int up = 1;
//	int down = 1;
//	int arr[50] = { 0 };
//	for (int i = 0; i < n; i++)
//	{
//		scanf("%d", &arr[i]);
//	}
//	for (int i = 0; i < n-1; i++)
//	{
//		if (arr[i] >= arr[i + 1])//前面元素大于后面
//		{
//			down = 0;
//		}
//		if (arr[i] < arr[i + 1])//后面元素大于前面
//		{
//			up = 0;
//		}
//	}
//	//如果是有序 那么down和up只能一个是1 一个是0
//	if ((up ^ down) == 1)
//	{
//		printf("sorted\n");
//	}
//	else {
//		printf("unsorted\n");
//	}
//	return 0;
//}


//有一个有序数字序列，从小到大排序，将一个新输入的数插入到序列中，保证插入新数后，序列仍然是升序。
//输入描述：
//第一行输入一个整数N(0≤N≤50)。
//
//第二行输入N个升序排列的整数，输入用空格分隔的N个整数。
//
//第三行输入想要进行插入的一个整数。
//输出描述：
//输出为一行，N + 1个有序排列的整数。
//

//#include<stdio.h>
//int main()
//{
//	int n = 0;
//	int insert = 0;
//	scanf("%d", &n);
//	int arr[50] = { 0 };
//	int i = 0;
//	//输入n个整数
//	for (i = 0; i < n; i++)
//	{
//		scanf("%d", &arr[i]);
//
//	}
//	//输入想要插入的数
//	scanf("%d", &insert);
//	//找到插入位置
//	for (i = 0; i < n; i++)
//	{
//		//1 2 3 5 6 7 8 9 0 0 0 0 0
//		//在中间
//		if (arr[i] <= insert && arr[i+1]>=insert )//此时i+1就是应该插入的位置
//		{
//			for (int j = n;j>=i+2 ; j--)
//			{
//				arr[j] = arr[j - 1];
//			}
//			arr[i + 1] = insert;
//			break;//记得这里插入要跳出 否则上面的循环还会继续
//		}
//		else if (insert >= arr[n - 1])
//		{
//			arr[n] = insert;
//			break;
//		}
//		else if (insert <= arr[0])
//		{
//			for (int j = n; j > 0; j--)
//			{
//				arr[j] = arr[j - 1];
//			}
//			arr[0] = insert;
//			break;
//		}
//
//	}
//	//打印
//	for (i = 0; i < n + 1; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//	return 0;
//}


//输入n个整数的序列，要求对这个序列进行去重操作。所谓去重，是指对这个序列中每个重复出现的整数，只保留该数第一次出现的位置，删除其余位置。
//输入描述：
//输入包含两行，第一行包含一个正整数n（1 ≤ n ≤ 1000），表示第二行序列中数字的个数；第二行包含n个整数（范围1~5000），用空格分隔。
//
//输出描述：
//输出为一行，按照输入的顺序输出去重之后的数字，用空格分隔。

//#include<stdio.h>
//int main()
//{
//
//	int n = 0;
//	scanf("%d", &n);
//	int arr[1000] = { 0 };
//	int i = 0;
//	for (i = 0; i < n; i++)
//	{
//		int flag = 0;
//		scanf("%d", &arr[i]);//先读取这个数
//		int j = 0;
//		for (j = 0; j < i; j++)
//		{
//			if (arr[j] == arr[i])//说明有重复
//			{	
//				flag = 1;
//			}
//		}
//		if (flag == 0)
//		{
//			printf("%d ", arr[i]);
//		}
//
//	}
//
//	return 0;
//}

//
//给定n个整数和一个整数x，小乐乐想从n个整数中判断x出现几次，请编程帮他实现。
//输入描述：
//共3行
//第一行，一个整数，表示n（1 <= n <= 100）。
//第二行，共输入n个整数，两个整数之间用空格分隔。
//第三行，输入一个整数，表示要查找的整数x。
//输出描述：

//#include<stdio.h>
//#include<stdlib.h>
//int main()
//{
//	int n, x;
//	scanf("%d", &n);
//	int i = 0;
//	int count =0;
//	int* arr = (int*)malloc(sizeof(int) * n);
//	for (i = 0; i < n; i++)
//	{
//		scanf("%d", &arr[i]);
//	}
//	scanf("%d", &x);
//	for (i = 0; i < n; i++)
//	{
//		if (x == arr[i])
//			count++;
//	}
//	printf("%d\n", count);
//	return 0;
//}


//用筛选法求n以内的素数。筛选法求解过程为：将2~n之间的正整数放在数组内存储，将数组中2之后的所有能被2整除的数清0，再将3之后的所有能被3整除的数清0 ，以此类推，直到n为止。数组中不为0 的数即为素数。
//输入描述：
//多组输入，每行输入一个正整数（不大于100）。
//输出描述：
//针对每行输入的整数n，输出两行，第一行，输出n之内（包括n）的素数，用空格分隔，
//
//第二行，输出数组中2之后被清0 的个数。每行输出后换行。

//#include<stdio.h>
//int main()
//{
//	int n = 0;
//	while (scanf("%d", &n) != EOF)
//	{
//		int arr[100] = { 0 };
//		int i = 0;
//		int count = 0;
//		//存入数组
//		for (i = 0; i < n - 1; i++)
//		{
//			arr[i] = i + 2;
//		}
//		int ret = 2;
//		while (ret<n)
//		{
//			for (i = ret; i <= n; i++)
//			{
//				if (arr[i] % ret == 0&&arr[i]!=0)//注意这里必须加一个arr[i]!=0 否则count会一直++
//				{
//					arr[i] = 0;
//					count++;
//				}
//			}
//			ret++;
//		}
//		for (i = 0; i < n; i++)
//		{
//			if (arr[i] != 0)
//			{
//				printf("%d ", arr[i]);
//			}
//		}
//		printf("\n%d\n", count);
//
//	}
//	return 0;
//}


//KiKi得到了一个n行m列的矩阵，现在他想知道第x行第y列的值是多少，请你帮助他完成这个任务。
//
//数据范围：1 \le n, m \le 5 \1≤n, m≤5  ，矩阵中的值满足 1 \le val \le 25 \1≤val≤25
//输入描述：
//第一行包含两个数n和m，表示这个矩阵包含n行m列。从2到n + 1行，每行输入m个整数（范围 - 231~231 - 1），用空格分隔，共输入n * m个数，表示矩阵中的元素。接下来一行输入x和y，用空格分隔，表示KiKi想得到的元素的位置。(1≤x≤n≤10，1≤y≤m≤10)
//
//输出描述：
//一行，输出一个整数值，为KiKi想知道的值。

//#include<stdio.h>
//int main()
//{
//	int n, m;
//	scanf("%d%d", &n, &m);
//	int arr[5][5] = { 0 };
//	if (n <= 5 && m <= 5)
//	{
//		int i = 0;
//		for (i = 0; i < n; i++)
//		{
//			int j = 0;
//			for (j = 0; j < m; j++)
//			{
				//scanf("%d", &arr[i][j]);
//
//			}
//		}
//		int x = 0;
//		int y = 0;
//		scanf("%d%d", &x, &y);
//		if (x <= n && y <= m)
//			printf("%d\n", arr[x-1][y-1]);
//
//	}
//	return 0;
//}

//KiKi想从n行m列的方阵队列中找到身高最高的人的位置，请你帮助他完成这个任务。
//
//输入描述：
//第一行包含两个整数n和m，表示这个方阵队列包含n行m列。
// 从2到n + 1行，每行输入m个整数（范围 - 231~231 - 1），用空格分隔，共输入n * m个数，表示方阵中的所有人的身高（保证输入身高都不相同）。(1≤x≤n≤10，1≤y≤m≤10)
//
//输出描述：
//一行，输出两个整数，用空格分隔，表示方阵中身高最高的人所在的行号和列号。

//#include<stdio.h>
//int main()
//{
//	int arr[10][10] = { 0 };
//	int n, m;
//	scanf("%d%d", &n, &m);
//	int i = 0;
//	int j = 0;
//	int h_est = arr[0][0];
//	int h_x = 0;
//	int h_y = 0;
//	for (i = 0; i < n; i++)
//	{
//		for (j = 0; j < m; j++)
//		{
//			scanf("%d", &arr[i][j]);
//			if (arr[i][j] > h_est)
//			{
//				h_est = arr[i][j];
//				h_x = i + 1;
//				h_y = j + 1;
//			}
//		}
//	}
//	printf("%d %d\n", h_x, h_y);
//	//printf("%d\n", h_est);
//
//	return 0;
//}


//描述
//KiKi得到了两个n行m列的矩阵，他想知道两个矩阵是否相等，请你回答他。(当两个矩阵对应数组元素都相等时两个矩阵相等)。
//
//输入描述：
//第一行包含两个整数n和m，表示两个矩阵包含n行m列，用空格分隔。
//
//从2到n + 1行，每行输入m个整数（范围 - 231~231 - 1），用空格分隔，共输入n * m个数，表示第一个矩阵中的元素。
//
//从n + 2行到2n + 1，每行输入m个整数（范围 - 231~231 - 1），用空格分隔，共输入n * m个数，表示第二个矩阵中的元素。
//1 < n, m < 10

//#include<stdio.h>
//int main()
//{
//	int n, m;
//	scanf("%d%d", &n, &m);
//	int arr1[10][10] = { 0 };
//	int arr2[10][10] = { 0 };
//	int i = 0;
//	int flag = 0;
//	for (i = 0; i < n; i++)
//	{
//		int j = 0;
//		for (j = 0; j < m; j++)
//		{
//			scanf("%d", &arr1[i][j]);
//		}
//	}	
//	for (i = 0; i < n; i++)
//	{
//		int j = 0;
//		for (j = 0; j < m; j++)
//		{
//			scanf("%d", &arr2[i][j]);
//		}
//	}
//	for (i = 0; i < n; i++)
//	{
//		int j = 0;
//		for (j = 0; j < m; j++)
//		{
//			if (arr1[i][j] != arr2[i][j])
//			{
//				flag = 1;
//			}
//		}
//	}
//	if (flag == 0)
//	{
//		printf("Yes\n");
//	}
//	else {
//		printf("No\n");
//	}
//	return 0;
//}

//输入NxM矩阵，矩阵元素均为整数，计算其中大于零的元素之和。
//
//输入描述：
//第一行为N M(N: 矩阵行数；M: 矩阵列数, 且M, N <= 10)，接下来的N行为矩阵各行。
//输出描述：
//一行，其中大于零的元素之和。

//#include<stdio.h>
//int main()
//{
//	int n, m;
//	scanf("%d%d", &n, &m);
//	int arr[10][10] = { 0 };
//	int sum = 0;
//	for(int i=0;i<n;i++)
//	{
//		for (int j = 0; j < m; j++)
//		{
//			scanf("%d", &arr[i][j]);
//			if (arr[i][j] > 0)
//			{
//				sum += arr[i][j];
//			}
//		}
//	}
//	printf("%d\n", sum);
//	return 0;
//}

//给你一个整数n，按要求输出n∗n的回型矩阵
//输入描述：
//输入一行，包含一个整数n
//
//1 <= n <= 19
//输出描述：
//输出n行，每行包含n个正整数
//思路： 一个个填数？？

//方法1：
//#include<stdio.h>
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	int ret = 1;
//	int arr[19][19] = { 0 };
//	// 定义边界 
//	int right = n;
//	int down = 0;
//	// 既然是填数 就要把初始坐标设置为 0,0
//	int x = 0, y = 0;
//	int flag = 1;
//	int i = 0;
//	for (i = 1; i <= n * n; i++)
//	{
//		// 向右走
//		if (flag == 1)
//		{
//			arr[x][y] = i;
//			y++;
//		}
//		// 向下走
//		else if (flag == 2)
//		{
//			arr[x][y] = i;
//			x++;
//		}
//		// 向左走
//		else if (flag == 3)
//		{
//			arr[x][y]=i;
//			y--;
//		}
//		// 向上走
//		else if (flag == 4)
//		{
//			arr[x][y] = i;
//			x--;
//		}
//		// 碰到右边界 开始向下 调整flag
//		if (y == right - 1 && x == down)
//		{
//			flag = 2;
//		}
//		// 碰到 下边界 开始向左
//		if (x == right - 1 && y == right - 1)
//		{
//			flag = 3;
//		}
//		// 碰到 左边界 开始向上 
//		// 每次向上 边界开始发生变化 
//		if (y == down && x == right - 1)
//		{
//			flag = 4;
//			right -- ;
//			down++;
//		}
//		// 碰到更新的上边界 开始向右 
//		if (x==down&&y==(down-1))
//		{
//			flag = 1;
//		}
//	}
//	for (i = 0; i < n; i++)
//	{
//		for (int j = 0; j < n; j++)
//		{
//			printf("%d ", arr[i][j]);
//		}
//		printf("\n");
//	}
//
//	return 0;
//}


//方法2：

#include<stdio.h>
int main()
{
	int arr[19][19] = { 0 };
	int n = 0;
	scanf("%d", &n);
	int count = 1;
	int a = n;
	int b = 0;
	while (count <= n * n)
	{
		//向右
		// 控制行的不变
		for (int i = b; i < a; i++)
		{
			arr[b][i] = count++;
		}
		// 向下
		// 控制列的不变
		for (int i = b+1; i < a; i++)
		{
			arr[i][a-1] = count++;
		}
		// 向左 
		for (int i = a - 2; i >= b;i--)
		{
			arr[a - 1][i] = count++;		
		}
		// 向上
		// 控制行的变化 列不变
		for (int i = a - 2; i > b; i--)
		{
			// 注意 虽然b+1 但是 此时仍然在b-1那一列
			arr[i][b] = count++;
		}
		/* 注意 需要在最后将边界变化 因为上面变化过程都是连续的 不可能在循环中改动*/
		a--;
		b++;

	}
	for (int i = 0; i < n; i++)
	{
		int j = 0;
		for (j = 0; j < n; j++)
		{
			printf("%2d ", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

